package com.cl.short_video_java.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeCloseResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cl.short_video_java.common.Const;
import com.cl.short_video_java.dto.OrderStats;
import com.cl.short_video_java.exception.WebException;
import com.cl.short_video_java.menum.AlipayStatus;
import com.cl.short_video_java.pojo.VideoShop;
import com.cl.short_video_java.pojo.VideoShopOrder;
import com.cl.short_video_java.pojo.VideoUser;
import com.cl.short_video_java.service.SysSettingService;
import com.cl.short_video_java.service.VideoShopOrderService;
import com.cl.short_video_java.mapper.VideoShopOrderMapper;
import com.cl.short_video_java.service.VideoShopService;
import com.cl.short_video_java.service.VideoUserService;
import com.cl.short_video_java.util.IdAssignUtil;
import com.cl.short_video_java.util.StringUtils;
import com.cl.short_video_java.vo.shop.OrderSearch;
import com.cl.short_video_java.vo.shop.OrderStatsVo;
import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author object
 * @description 针对表【video_shop_order】的数据库操作Service实现
 * @createDate 2024-10-31 15:58:59
 */
@Service
@Slf4j
public class VideoShopOrderServiceImpl extends ServiceImpl<VideoShopOrderMapper, VideoShopOrder>
		implements VideoShopOrderService {

	private VideoUserService videoUserService;
	private VideoShopService videoShopService;
	private VideoShopOrderMapper videoShopOrderMapper;
	private AlipayClient alipayClient;
	private SysSettingService settingService;

	VideoShopOrderServiceImpl(VideoUserService videoUserService,
							  VideoShopService videoShopService,
							  VideoShopOrderMapper videoShopOrderMapper,
							  AlipayClient alipayClient,
							  SysSettingService settingService) {
		this.videoUserService = videoUserService;
		this.videoShopService = videoShopService;
		this.videoShopOrderMapper = videoShopOrderMapper;
		this.alipayClient = alipayClient;
		this.settingService = settingService;
	}

	private final ReentrantLock lock = new ReentrantLock();

	@Override
	public Page<VideoShopOrder> page(OrderSearch orderSearch) {
		Page<VideoShopOrder> page = this.page(new Page<>(orderSearch.getPageNum(), orderSearch.getPageSize()), new QueryWrapper<VideoShopOrder>()
				.like(StringUtils.isNotEmpty(orderSearch.getOrderId()), "order_id", orderSearch.getOrderId())
				.eq(StringUtils.isNotEmpty(orderSearch.getPayType()), "pay_type", orderSearch.getPayType())
				.eq(orderSearch.getStatus() != null, "status", orderSearch.getStatus())
				.like(StringUtils.isNotEmpty(orderSearch.getPhone()), "phone", orderSearch.getPhone())
				.ge(orderSearch.getCreateTime() != null, "create_time", orderSearch.getCreateTime())
				.le(orderSearch.getPayTime() != null, "pay_time", orderSearch.getPayTime())
				.eq("is_delete", 0)
		);
		for (VideoShopOrder order : page.getRecords()) {
			VideoUser user = videoUserService.getOne(new QueryWrapper<VideoUser>()
					.select("phone", "nickname")
					.eq("id", order.getUserId())
			);
			VideoShop shop = videoShopService.getOne(new QueryWrapper<VideoShop>()
					.select("title")
					.eq("id", order.getShopId()));
			order.setVideoUser(user);
			order.setVideoShop(shop);
		}
		return page;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void del(List<String> ids) {
		for (String id : ids) {
			this.update(new UpdateWrapper<VideoShopOrder>().eq("order_id", id).set("is_delete", 1));
		}
	}

	@Override
	public List<OrderStats> stats(OrderStatsVo orderStats) {
		List<OrderStats> list = new ArrayList<>();
		if ("year".equals(orderStats.getType())) {
			list = videoShopOrderMapper.year(orderStats);
		} else if ("month".equals(orderStats.getType())) {
			list = videoShopOrderMapper.month(orderStats);
		} else if ("day".equals(orderStats.getType())) {
			list = videoShopOrderMapper.day(orderStats);
		}
		// 数据补齐
		list = additions(list, orderStats.getType());
		return list;
	}

	/**
	 * 创建订单
	 *
	 * @param shopId  订单编号
	 * @param request 请求信息
	 * @return
	 */
	@Override
	public VideoShopOrder createOrder(Integer shopId, HttpServletRequest request) {
		VideoUser user = videoUserService.getCurrentUser(request, Const.GRADE_USER);
		VideoShopOrder shopOrder = this.getOne(new QueryWrapper<VideoShopOrder>()
				.eq("user_id", user.getId())
				.eq("shop_id", shopId)
				.eq("status", 0)
				.eq("is_delete", 0)
		);
		if (shopOrder != null) {
			log.info("存在一个订单=====" + shopOrder);
			// 如果存在一个未支付的订单，就返回
			return shopOrder;
		}
		VideoShop videoShop = videoShopService.getById(shopId);
		if (videoShop == null) {
			throw new WebException("当前商品不存在");
		}

		VideoShopOrder order = new VideoShopOrder();
		order.setUserId(user.getId());
		order.setShopId(shopId);
		order.setStatus(0);
		order.setCreateTime(LocalDateTime.now());
		order.setPayType("alipay");
		order.setIsDelete(0);
		order.setPrice(videoShop.getPrice());
		BigDecimal bigDecimal = new BigDecimal(videoShop.getDiscount());
		order.setPayPrice(videoShop.getPrice().multiply(bigDecimal).setScale(2, BigDecimal.ROUND_HALF_UP));
		order.setOrderId(IdAssignUtil.nextId());
		order.setTitle(videoShop.getTitle());
		this.saveOrUpdate(order);
		return order;

	}


	/**
	 * 处理订单业务
	 *
	 * @param params 支付宝回调参数
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void processOrder(Map<String, String> params) {
		String tradeNo = params.get("out_trade_no");
		log.info("订单处理=============》" + tradeNo);
		VideoShopOrder shopOrder = this.getOne(new QueryWrapper<VideoShopOrder>().eq("order_id", tradeNo));
		shopOrder.setStatus(3);
		this.updateById(shopOrder);
		VideoShop one = videoShopService.getOne(new QueryWrapper<VideoShop>().eq("id", shopOrder.getShopId()));
		one.setBuyCount(one.getBuyCount() + 1);
		videoShopService.updateById(one);

		// 用户升级
		videoUserService.upgrade(one.getId(), shopOrder.getUserId(), shopOrder.getPrice());
	}


	/**
	 * 取消订单
	 *
	 * @param orderNo
	 */
	@Override
	public void cancel(String orderNo) {

		// 调用支付宝统一收单交易关闭接口
		this.closeOrder(orderNo);

		this.update(new UpdateWrapper<VideoShopOrder>().eq("order_id", orderNo).set("status", 2));
	}

	@Override
	public String queryOrder(String orderNo) {
		log.info("查询订单信息=====================>" + orderNo);
		try {
			// 构造请求参数以调用接口
			AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
			AlipayTradeQueryModel model = new AlipayTradeQueryModel();
			model.setOutTradeNo(orderNo);
			request.setBizModel(model);
			AlipayTradeQueryResponse response = alipayClient.execute(request);
			JSONObject jsonObject = JSONObject.parseObject(response.getBody());
			String isSuccess = jsonObject.getJSONObject("alipay_trade_query_response").get("msg").toString();
			if ("Success".equals(isSuccess)) {
				log.info("查询订单成功====================>" + response.getBody());
				return response.getBody();
			} else {
				log.info("查询订单失败====================>" + response.getBody());
				return null;
			}
		} catch (AlipayApiException e) {
			throw new RuntimeException(e);
		}

	}

	/**
	 * 根据订单号 调用支付宝查单接口，核实订单状态
	 * 如果订单已支付，则记录相关信息，并修改订单状态
	 * 如果订单未支付，则调用关单接口，关闭订单
	 * 如果订单为创建，则直接更新订单
	 *
	 * @param orderId
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public void checkOrderStatus(String orderId) {
		String s = queryOrder(orderId);
		log.info("查看订单状态并关单=================>" + s);
		if (s == null) {
//			this.update(new UpdateWrapper<VideoShopOrder>().eq("order_id", orderId).set("status", 2));
			return;
		}
		Gson gson = new Gson();
		HashMap<String, LinkedTreeMap> hashMap = gson.fromJson(s, HashMap.class);
		LinkedTreeMap response = hashMap.get("alipay_trade_query_response");
		String status = (String) response.get("trade_status");
		if (AlipayStatus.WAIT_BUYER_PAY.getType().equals(status) || AlipayStatus.TRADE_CLOSED.getType().equals(status)) {
			log.info("核实订单未支付创建=====>" + status);
			this.closeOrder(orderId);
			this.update(new UpdateWrapper<VideoShopOrder>().eq("order_id", orderId).set("status", 2).set("is_delete", 1));
		} else if (AlipayStatus.TRADE_SUCCESS.getType().equals(status) || AlipayStatus.TRADE_FINISHED.getType().equals(status)) {
			log.info("订单已支付完成=====>" + status);
			this.update(new UpdateWrapper<VideoShopOrder>().eq("order_id", orderId).set("status", 3));
			Map<String, String> map = new HashMap<>();
			map.put("out_trade_no", orderId);
			this.processOrder(map);
		}
	}

	@Override
	public Page<VideoShopOrder> getByUserOrder(Integer pageNum, HttpServletRequest request) {
		VideoUser user = videoUserService.getCurrentUser(request, Const.GRADE_USER);
		Page<VideoShopOrder> page = this.page(new Page<>(pageNum, 20), new QueryWrapper<VideoShopOrder>()
				.eq("user_id", user.getId())
				.eq("is_delete", 0)
				.orderByDesc("pay_time")
		);
		if (page.getRecords().size() <= 0) {
			return page;
		}
		Integer rate = Integer.valueOf(settingService.getSysSettingByKey("sys_exchange_rate"));
		for (VideoShopOrder order : page.getRecords()) {
			VideoShop videoShop = videoShopService.getById(order.getShopId());
			if (videoShop.getType() == 2) {
				//金币商品
				BigDecimal price = videoShop.getPrice();
				double v = price.doubleValue() * rate;
				order.setGold((int) v);
				order.setShopType(2);
			}
		}
		return page;
	}

	/**
	 * 支付宝统一收单关闭接口
	 *
	 * @param orderNo 订单编号
	 */
	private void closeOrder(String orderNo) {
		try {
			AlipayTradeCloseRequest req = new AlipayTradeCloseRequest();
			JSONObject jsonObject = new JSONObject();

			jsonObject.put("out_trade_no", orderNo);
			req.setBizContent(jsonObject.toString());
			AlipayTradeCloseResponse response = alipayClient.execute(req);
			if (response.isSuccess()) {
				log.info("关单成功========>", response.getBody());
			} else {
				log.error("关单失败========>", response.getCode() + ":" + response.getMsg());
			}
		} catch (AlipayApiException e) {
			throw new WebException("关单失败");
		}
	}

	/**
	 * 填充数据
	 *
	 * @param list
	 * @param type
	 * @return
	 */
	private List<OrderStats> additions(List<OrderStats> list, String type) {
		long count = 0;
		if ("month".equals(type)) {
			count = 12;
		} else if ("day".equals(type)) {
			count = 31;
		}
		for (int i = 1; i <= count; i++) {
			boolean flag = false;
			for (OrderStats orderStats : list) {
				if (orderStats.getDate() == i) {
					// 存在当前时间节点
					flag = true;
				}
			}
			if (!flag) {
				list.add(new OrderStats(0, i));
			}
		}
		return list;
	}


}




